package cn.chendd.cofig.enums;

import cn.chendd.cofig.filters.GatewayContext;
import cn.chendd.cofig.utils.MultipleBodyContent;
import cn.chendd.logger.GatewayLogger;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.ContentDisposition;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * http请求参数范围枚举定义
 *
 * @author chendd
 * @date 2022/12/27 22:02
 */
public enum  HttpParamScopeEnum {

    /**
     * 全部参数
     */
    All {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            throw new UnsupportedOperationException("HttpParamScopeEnum.All.log()");
        }
    },
    /**
     * 常规参数
     */
    General {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            GatewayLogger.getLogger().debug("【General】");
            GatewayLogger.getLogger().debug("Request URL: {}" , request.getURI());
            GatewayLogger.getLogger().debug("Request Method: {}" , request.getMethodValue());
            GatewayLogger.getLogger().debug("Status Code: {}" , response.getStatusCode());
            GatewayLogger.getLogger().debug("Remote Address: {}" , request.getRemoteAddress());
            GatewayLogger.getLogger().debug("Local Address: {}" , request.getLocalAddress());
        }
    },
    /**
     * 响应头
     */
    ResponseHeaders {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            HttpHeaders headers = response.getHeaders();
            if (headers == null || headers.isEmpty()) {
                GatewayLogger.getLogger().debug("【Response Headers】无");
                return;
            }
            GatewayLogger.getLogger().debug("【Response Headers】");
            Map<String, String> headerMap = headers.toSingleValueMap();
            headerMap.forEach((key , value) -> {
                GatewayLogger.getLogger().debug("{}: {}" , key , value);
            });
        }
    },
    /**
     * 请求头
     */
    RequestHeaders {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            HttpHeaders headers = request.getHeaders();
            if (headers == null || headers.isEmpty()) {
                GatewayLogger.getLogger().debug("【Request Headers】无");
                return;
            }
            GatewayLogger.getLogger().debug("【Request Headers】");
            Map<String, String> headerMap = headers.toSingleValueMap();
            headerMap.forEach((key , value) -> {
                GatewayLogger.getLogger().debug("{}: {}" , key , value);
            });
        }
    },
    /**
     * 参数值
     */
    QueryStringParameters {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            MultiValueMap<String, String> queryParams = request.getQueryParams();
            if (queryParams == null || queryParams.isEmpty()) {
                GatewayLogger.getLogger().debug("【Query String Parameters】无");
                return;
            }
            GatewayLogger.getLogger().debug("【Query String Parameters】");
            queryParams.forEach((key , values) -> {
                int size = values.size();
                if (size == 1) {
                    GatewayLogger.getLogger().debug("{}: {}" , key , values.get(0));
                } else {
                    GatewayLogger.getLogger().debug("{}: {}" , key , values);
                }
            });
        }
    },
    /**
     * 请求载荷
     */
    Payload{
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.REQUEST_BODY_CACHE_GATEWAY_CONTEXT);
            if (gatewayContext == null) {
                GatewayLogger.getLogger().debug("【Query Payload】无");
                return;
            }
            long contentLength = request.getHeaders().getContentLength();
            String requestBody = gatewayContext.getRequestBody();
            boolean notNull = StringUtils.isNotEmpty(requestBody);
            MediaType contentType = request.getHeaders().getContentType();
            boolean multipart = MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType);
            //如果是文件上传
            if (contentLength > GatewayContext.LOG_UPLOAD_MAX_SIZE && notNull && multipart) {
                GatewayLogger.getLogger().debug("【Query Payload】");
                //输出上传文件名称
                GatewayLogger.getLogger().debug("请求包含文件上传，且大于 {} MB" , GatewayContext.LOG_UPLOAD_MAX_SIZE / GatewayContext.LOG_UPLOAD_SIZE);
            } else if (notNull && multipart) {
                GatewayLogger.getLogger().debug("【Query Payload】");
                //输出json格式参数
                GatewayLogger.getLogger().debug(MultipleBodyContent.getBodyContent(requestBody));
            } else if (notNull) {
                GatewayLogger.getLogger().debug("【Query Payload】");
                //输出非文件上传请求的json格式
                GatewayLogger.getLogger().debug(requestBody);
            } else {
                GatewayLogger.getLogger().debug("【Query Payload】无");
            }
        }
    },
    /**
     * 响应结果
     */
    Response {
        @Override
        protected void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response) {
            GatewayContext gatewayContext = exchange.getAttribute(GatewayContext.REQUEST_BODY_CACHE_GATEWAY_CONTEXT);
            if (gatewayContext == null) {
                GatewayLogger.getLogger().debug("【Response】无");
                return;
            }
            GatewayLogger.getLogger().debug("【Response】");
            HttpHeaders headers = response.getHeaders();
            MediaType contentType = headers.getContentType();
            if (MediaType.APPLICATION_OCTET_STREAM.isCompatibleWith(contentType)) {
                //如果是文件下载则直接显示文件名称
                ContentDisposition contentDisposition = headers.getContentDisposition();
                if (contentDisposition != null) {
                    assert contentDisposition.getFilename() != null;
                    String fileName = new String(contentDisposition.getFilename().getBytes(StandardCharsets.ISO_8859_1) , StandardCharsets.UTF_8);
                    GatewayLogger.getLogger().debug("《{}》", fileName);
                    return;
                }
            }
            GatewayLogger.getLogger().debug(gatewayContext.getResponseBody());
        }
    },
    ;

    /**
     * 输出日志
     * @param paramScopes 记录参数范围
     * @param exchange 交换机
     */
    public static void execute(List<String> paramScopes , ServerWebExchange exchange) {
        if (paramScopes == null || paramScopes.isEmpty()) {
            return;
        }
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        //输入全部日志
        if (paramScopes.contains(All.name())) {
            HttpParamScopeEnum[] items = HttpParamScopeEnum.values();
            for (HttpParamScopeEnum item : items) {
                if (All.equals(item)) {
                    continue;
                }
                item.log(exchange , request , response);
            }
            return;
        }
        //输出设置的部分日志
        for (String item : paramScopes) {
            HttpParamScopeEnum.valueOf(item).log(exchange , request , response);
        }
    }

    /**
     * 定义记录日志方法
     */
    protected abstract void log(ServerWebExchange exchange , ServerHttpRequest request, ServerHttpResponse response);

}
